昨天我們的圖表已經成功地接上資料,為了讓使用者能客制喜歡的顏色,我們今天就要做一個可以讓使用者設定顏色的功能,順便以此來練習react的操作。
首先是先做好操作的ui,為了快速我使用了一個modal套件:http://reactcommunity.org/react-modal/
並用local state的方式控制這個modal是否要顯示。
const [modalIsOpen, setModalIsOpen] = React.useState(false);
//...
<Modal
isOpen={isModalOpen}
style={{
content: {
background: '#FFFFFF',
borderRadius: 9,
width: 356,
minHeight: 386,
top: '50%',
left: '50%',
right: 'auto',
bottom: 'auto',
marginRight: '-50%',
transform: 'translate(-50%, -50%)'
},
overlay: {
backgroundColor: 'rgba(0, 0, 0, 0.7)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}
}}
onRequestClose={() => setIsModalOpen(false)}
></Modal>
//...
接著同樣以local state的形式來存取色碼的陣列,並傳進去heatmap的component中。
const [colors, setColors] = useState([
{
color: '#F3F3F3',
showPicker: false
},
{
color: '#84B6FD',
showPicker: false
},
{
color: '#8E87FA',
showPicker: false
}
]);
const addColor = useCallback(() => {
setColors([
...colors,
{
color: '#fafafa',
showPicker: false
}
]);
}, [colors]);
const deleteColor = useCallback(
(index) => {
setColors([...colors].filter((e, i) => i !== index));
},
[colors]
);
// ...
// modal 裡面
<table style={{ marginTop: 48 }}>
<tbody>
<tr>
<td className="label">Color</td>
<td>
{colors.map((item, i) => (
<div className="color-group" key={i}>
<div
className="color-block"
style={{ backgroundColor: item.color }}
></div>
<img
src={deleteIcon}
alt=""
onClick={() => deleteColor(i)}
/>
</div>
))}
// 為了避免顏色太多反而太亂,讓使用者最多新增五個
{colors.length < 5 && (
<img
src={addIcon}
alt=""
className="add-icon"
onClick={addColor}
/>
)}
</td>
</tr>
</tbody>
</table>
//...
再來就是顏色選擇器,應該一般來說比較少用到,我們要用的是這個套件:https://casesandberg.github.io/react-color/
,以一個布林值做判斷,true時才顯示picker。另外就照文件寫的監聽選擇色彩的事件,把顏色的色碼更新到array裡面。
const toggleColorPicker = useCallback(
(index) => {
const newColors = [...colors];
newColors[index].showPicker = !colors[index].showPicker;
setColors(newColors);
},
[colors]
);
const updateColor = useCallback(
(index, color) => {
const newColors = [...colors];
newColors[index].color = color.hex;
setColors(newColors);
},
[colors]
);
// ...
{colors.map((item, i) => (
<div className="color-group" key={i}>
{item.showPicker && (
<div className="color-picker">
<SketchPicker
color={item.color}
onChangeComplete={(color) => updateColor(i, color)}
/>
</div>
)}
<div
className="color-block"
style={{ backgroundColor: item.color }}
onClick={() => toggleColorPicker(i)}
></div>
<img
src={deleteIcon}
alt=""
onClick={() => deleteColor(i)}
/>
</div>
))}
// ...